#pragma once

#include "RoomDefines.h"
#include "IActiveObject.h"

namespace RoomFW {

//
// Forward declare portal for pointers.
//
class Portal;
typedef ::boost::shared_ptr<Portal> PortalSP;

//
// Class:	Binding
//
// Description:	Base class for a ROOM binding.  A binding is what connects
//				two ports or port-like objects (e.g. portal).
//
// Author:	Andrew Sage
//
class Binding
{
public:

	//
	// Method:	~Binding
	//
	// Description:	Virtual destructor to ensure derived class destructors called.
	//
	virtual ~Binding() {};
};

//
// Typedef a smart pointer.
//
typedef ::boost::shared_ptr<Binding> BindingSP;

//
// Typedef a list.
//
typedef std::list<BindingSP> BindingList;

//
// Class:	Binding
//
// Description:	Binding between ports on two IActiveObject derived objects.
//
// Author:	Andrew Sage
//
class ActiveObjectsBinding : public Binding
{
public:

	//
	// Method:	ActiveObjectsBinding
	//
	// Description:	Constructor
	//
	// Parameters:
	//
	//	objectA - First object.
	//
	//	portA -	Primary Port index on first object.
	//
	//	objectB - Second object.
	//
	//	portB -	Primary Port index on second object.
	//
	ActiveObjectsBinding(IActiveObjectSP objectA, PortIndex::PrimaryIndex portA, IActiveObjectSP objectB, PortIndex::PrimaryIndex portB)
		throw (std::runtime_error);

	//
	// Method:	~ActiveObjectsBinding
	//
	// Description:	Virtual destructor.
	//
	virtual ~ActiveObjectsBinding();

private:

	//
	// Save binding parameters to un-bind on destruction.
	//
	IActiveObjectSP objectA_;
	PortIndex portA_;
	IActiveObjectSP objectB_;
	PortIndex portB_;
};

//
// Typedef a smart pointer.
//
typedef ::boost::shared_ptr<ActiveObjectsBinding> ActiveObjectsBindingSP;

//
// Class:	PortalBinding
//
// Description:	Binding between a portal and a port on an IActiveObject derived object.
//
// Author:	Andrew Sage
//
class PortalBinding : public Binding
{
public:

	//
	// Method:	PortalBinding
	//
	// Description:	Constructor
	//
	// Parameters:
	//
	//	portal - Portal to bind.
	//
	//	object - Object to bind.
	//
	//	port -	Port index on object to bind.  Generally pass the enum or primary port index only.
	//
	PortalBinding(PortalSP portal, IActiveObjectSP object, PortIndex::PrimaryIndex port)
		throw (std::runtime_error);

	//
	// Method:	~PortalBinding
	//
	// Description:	Virtual destructor.
	//
	virtual ~PortalBinding();

private:

	//
	// Remember the portal for unbind.
	//
	PortalSP portal_;
};

//
// Typedef a smart pointer.
//
typedef ::boost::shared_ptr<PortalBinding> PortalBindingSP;

//
// Class:	BindingWrapper
//
// Description:	Wraps another binding.  Used for DynamicBinding implementation.
//
// Author:	Andrew Sage
//
class BindingWrapper : public Binding
{
public:

	//
	// Method:	BindingWrapper
	//
	// Description:	Constructor
	//
	// Parameters:
	//
	//	innerBinding - Binding to wrap.
	//
	BindingWrapper(BindingSP innerBinding);

	//
	// Method:	~BindingWrapper
	//
	// Description:	Virtual destructor.
	//
	virtual ~BindingWrapper();

	//
	// Method:	unbind
	//
	// Description:	Reset wrapped binding.
	//
	// Parameters:	None.
	//
	void unbind();

private:

	//
	// Wrapped binding.
	//
	BindingSP innerBinding_;
};

//
// Typedef a smart pointer.
//
typedef ::boost::shared_ptr<BindingWrapper> BindingWrapperSP;

//
// Class:	DynamicBinding
//
// Description:	Binding returned from calls to create a dynamic binding.
//
// Author:	Andrew Sage
//
class DynamicBinding : public Binding
{
public:

	//
	// Method:	DynamicBinding
	//
	// Description:	Constructor
	//
	// Parameters:
	//
	//	innerBinding - Wrapped binding.
	//
	DynamicBinding(BindingWrapperSP innerBinding);

	//
	// Method:	~DynamicBinding
	//
	// Description:	Virtual destructor.
	//
	virtual ~DynamicBinding();

private:

	//
	// Wrapped binding.
	//
	BindingWrapperSP innerBinding_;
};

//
// Typedef a smart pointer.
//
typedef ::boost::shared_ptr<DynamicBinding> DynamicBindingSP;


}
